﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Facade.Manager.Abstract;

using Domain.Model;

using DataAccess.Repositories;

namespace Facade.Manager
{
    public sealed class ProjectManager : AbstractManager
    {
        #region members

        private static readonly ProjectManager instance = new ProjectManager();

        private ProjectRepository projectRepository;
 
        private List<Project> projects;

        #endregion

        #region ProjectManager

        private ProjectManager()
        {
            projectRepository = new ProjectRepository();
            
            projects = new List<Project>();
        }

        public static ProjectManager Instance
        {
            get 
            {
                return instance;
            }
        }

        #endregion

        #region public methods

        public List<Project> GetAllProjects()
        {
            projects = projectRepository.GetAll() as List<Project>;
            return projects;
        }

        public List<Project> GetAllStandaloneProjects()
        {
            return projectRepository.GetStandaloneProjects() as List<Project>;
        }

        public Project GetProjectById(int id)
        {
            Project match = null;
            projects = projectRepository.GetAll() as List<Project>;

            foreach (var project in projects)
            {
                if (project.Id == id)
                    match = project;
            }

            return match;
        }

        public void SaveProject(Project project)
        {
            projects.Add(project);

            projectRepository.Add(project);
        }

        public void UpdateProject(int programId, Project project)
        {
            var original = GetProjectById(project.Id);

            Program program = null;

            if (programId != 0)
                program = PortfolioManager.Instance.GetProgramById(programId);

            if (original != null )
            {
                original = project;
                original.Program = program;
                projectRepository.Update(original);
            }
        }

        public void AddSubproject(int projectId, Subproject subproject)
        {
            var project = ProgramManager.Instance.GetProjectById(projectId);
            project.AddSubProject(subproject);

            projectRepository.Update(project);
        }

        public void DeleteProject(Project project)
        {
            projects.Remove(project);

            projectRepository.Delete(project);
        }

        public Boolean AddProjectTask(int projectId, ProjectTask task)
        {
            var project = projectRepository.GetById(projectId);
            if (project != null)
            {
                project.AddTask(task);
                projectRepository.Update(project);

                return true;
            }

            return false;
        }

        public Boolean UpdateProjectTask(int projectId, ProjectTask task)
        { 
            var project = projectRepository.GetById(projectId);
            if (project != null)
            {
                project.UpdateTask(task);
                projectRepository.Update(project);

                return true;
            }

            return false;
        }

        public Boolean DeleteProjectTask(int projectId, ProjectTask task)
        {
            var project = projectRepository.GetById(projectId);
            if (project != null)
            {
                project.RemoveTask(task);
                projectRepository.DeleteProjectTask(task);

                return true;
            }

            return false;
        }

        public ProjectTask GetProjectTaskById(int taskId)
        {
            return projectRepository.GetTaskById(taskId);
        }

        #endregion

        #region internal methods

        /// <summary>
        /// Delete ProjectDetail with specific name from
        /// all projects. 
        /// This method can only be called from other managers.
        /// </summary>
        /// <param name="name"></param>
        internal void DeleteDetailFromProjects(string name)
        {
            projectRepository.DeleteDetailFromProjects(name);

            foreach (var project in projects)
            {
                project.RemoveDetail(name);
            }
        }

        #endregion
    }
}